package com.play.ballen.home.task

import android.app.*
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.core.app.NotificationCompat
import com.hjq.toast.ToastUtils
import com.play.ballen.R
import com.play.ballen.home.ui.PlayCountActivity
import com.yuven.baselib.utils.Logger
import com.yuven.baselib.utils.ResourceUtil

class StepService : Service(), SensorEventListener {

    // Binder given to clients
    private val binder = LocalBinder()

    private var sensorManager: SensorManager? = null
    private var sensor: Sensor? = null
    private var sensorRegisterResult = false   //步测传感器是否注册成功

    private val notifyId = 1000
    private var channelId = "stepDetector"
    private lateinit var notifyManager: NotificationManager
    private lateinit var notificationBuilder: NotificationCompat.Builder
    private var wakeLock: PowerManager.WakeLock? = null
    private val wakeLockTag = "ballen:step_detector"
    private var stepSystemLastTotal = 0f

    override fun onCreate() {
        super.onCreate()
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
        Logger.i("StepService.onCreate sensor = $sensor")

        val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag)
        Logger.i("StepService.onCreate wakeLock = $wakeLock")

        TaskUtil.stepNotificationUpdateCallBack = { stepCount ->
            Logger.i("TaskUtil.stepNotificationUpdateCallBack invoke stepCount = $stepCount")
            updateNotification()
        }
        TaskUtil.onCompleteCallBack = {
            Logger.i("TaskUtil.onCompleteCallBack invoke")
            StepServiceUtil.unregisterSensor()
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    inner class LocalBinder : Binder() {
        // Return this instance of LocalService so clients can call public methods
        fun getService(): StepService = this@StepService
    }

    override fun onBind(intent: Intent): IBinder {
        Logger.i("StepService.onBind")
        return binder
    }

    override fun onUnbind(intent: Intent?): Boolean {
        Logger.i("StepService.onUnbind")
        return super.onUnbind(intent)
    }

    override fun onDestroy() {
        super.onDestroy()
        Logger.i("StepService.onDestroy")
    }

    fun stepSensorAvailable(): Boolean {
        Logger.i("StepService.stepSensorAvailable sensor = $sensor")
        return sensor != null
    }

    fun registerSensor() {
        Logger.i("StepService.registerSensor sensorRegisterResult = $sensorRegisterResult")
        if (sensor == null) {
            ToastUtils.show(ResourceUtil.getString(R.string.step_sensor_not_available))
            return
        }
        if (sensorRegisterResult) {
            return
        }
        sensorRegisterResult =
            sensorManager?.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST)
                ?: false

        if (sensorRegisterResult) {
            wakeLock?.acquire(TaskUtil.getPlayCountInfo()!!.time * 1000)
        }

        Logger.i("StepService.registerSensor result = $sensorRegisterResult")
    }

    fun unregisterSensor() {
        Logger.i("StepService.unregisterSensor, sensorRegisterResult = $sensorRegisterResult")
        if (!sensorRegisterResult) {
            return
        }
        wakeLock?.release()
        sensorManager?.unregisterListener(this, sensor)
        sensorRegisterResult = false
        stepSystemLastTotal = 0f
    }

    override fun onSensorChanged(event: SensorEvent?) {
        if (event == null) {
            return
        }

        if (event.sensor.type == Sensor.TYPE_STEP_COUNTER) {
            val systemValue = event.values[0]
            val step = if (stepSystemLastTotal == 0f) {
                1f
            } else {
                systemValue - stepSystemLastTotal
            }
            Logger.i("StepService.onSensorChanged systemValue = $systemValue, stepSystemLastTotal = $stepSystemLastTotal, step = $step")
            stepSystemLastTotal = systemValue

            if (step != 0f) {
                TaskUtil.stepCountIncrement(step.toInt())
            }
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {

    }

    fun requestStartForeground(context: Context) {
        Logger.i("StepService.requestStartForeground")
        startForeground(notifyId, createNotification(context))
    }

    fun requestStopForeground() {
        Logger.i("StepService.requestStopForeground")
        stopForeground(true)
        stopSelf()
    }

    private fun createNotification(context: Context): Notification {
        Logger.i("StepService.createNotification")
        notifyManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        //创建Android8.0通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                ResourceUtil.getString(R.string.step_notify_name),
                NotificationManager.IMPORTANCE_DEFAULT
            ).apply {
                enableLights(true) //是否在桌面icon右上角展示小红点
                lightColor = Color.RED //小红点颜色
                setShowBadge(true) //是否在久按桌面图标时显示此渠道的通知
                description = ResourceUtil.getString(R.string.step_notify_description)
            }
            notifyManager.createNotificationChannel(channel)
        }

        notificationBuilder = NotificationCompat.Builder(this, channelId)
        notificationBuilder.setOnlyAlertOnce(true) //铃声和震动均只执行一次
        notificationBuilder.setSmallIcon(R.mipmap.ic_launcher)
        notificationBuilder.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL)
        notificationBuilder.setContentTitle(ResourceUtil.getString(R.string.step_notify_name))
        notificationBuilder.setContentText(
            ResourceUtil.getString(
                R.string.step_notify_content,
                TaskUtil.getStepCount(),
                TaskUtil.getTaskCount()
            )
        )
        notificationBuilder.setAutoCancel(false)
        notificationBuilder.setOngoing(true) //不允许滑动删除当前通知

        val intent = Intent(this, PlayCountActivity::class.java)
        val contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
        notificationBuilder.setContentIntent(contentIntent)
        return notificationBuilder.build()
    }

    private fun updateNotification() {
        Logger.i("StepService.updateNotification")
        notificationBuilder.setContentTitle(ResourceUtil.getString(R.string.step_notify_name))
        notificationBuilder.setContentText(
            ResourceUtil.getString(
                R.string.step_notify_content,
                TaskUtil.getStepCount(),
                TaskUtil.getTaskCount()
            )
        )
        notifyManager.notify(notifyId, notificationBuilder.build())
    }

}